#!/usr/bin/python3
# -*- coding:UTF-8 -*-

import os
import argparse
import json
import time

import AutoExecUtils
import JmxUtils

def usage():
    pname = os.path.basename(__file__)
    print(pname + " --node <host node> --jmxport <jmx port> --username <authenticate username> --password <authenticate password> --verbose")
    exit(1)

def memDivide( value ):
    if value == -1 or value == 0:
        return value
    return round(value/1024/1024)

def usageDivide( molecule , denominator ):
    if denominator == -1 or denominator == 0:
        return 0
    return round((molecule/denominator)*100)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--jmxport', default='', help='tomcat process jmx rmi server port')
    parser.add_argument('--username', default='', help='jmx authenticate username')
    parser.add_argument('--password', default='', help='jmx authenticate password')
    parser.add_argument('--verbose', default='', help='verbose output')

    args = parser.parse_args()
    isVerbose = int(args.verbose)
    node = os.getenv('AUTOEXEC_NODE')
    if node != None and node != '':
        node = json.loads(node)

    host = ''
    port = ''
    resourceId = 0 
    jmxport = args.jmxport
    username = args.username
    password = args.password

    if (node != None):
        host = node['host']
        if 'protocolPort' in node :
            port = node['protocolPort']
        elif 'port' in node:
            port = node['port']
        
        if (jmxport is None or jmxport =='' ):
            jmxport = port
        
        resourceId = node['resourceId']

    if (host == '' or jmxport == ''):
        usage()

    tomcat = {
        "MGMT_IP"     : host,
        "PORT"        : port,
        "_OBJ_CATEGORY": "INS",
        "_OBJ_TYPE"    : "Tomcat",
        "RESOURCE_ID" : resourceId,
        "AVAILABILITY": 0
    }
    startTime = time.time()
    JmxUtils = JmxUtils.JmxUtils(host , jmxport , username , password , isVerbose )
    (ret , errMsg) = JmxUtils.queryCheck("java.lang:type=Runtime" , "Uptime")
    timeConsume = round(time.time() - startTime, 4)
    if ret == 1:
        memory = []
        for attribute in ["HeapMemoryUsage" , "NonHeapMemoryUsage"] :
            ins = {}
            result = JmxUtils.queryBeanByNameAndAtrribute("java.lang:type=Memory" , attribute)
            data = result[attribute]
            max = memDivide(data['max'])
            used = memDivide(data['used'])
            init = memDivide(data['init'])
            committed = memDivide(data['committed'])
            ins['NAME'] = attribute
            ins['MAX'] = max
            ins['USED'] = used
            ins['INIT'] = init
            ins['COMMITTED'] = committed
            ins['USAGE'] = usageDivide(used , max)
            memory.append(ins)
        tomcat["MEMORY"] = memory
        
        memoryPool = []
        for name in ["Code Cache","Metaspace","Compressed Class Space","Par Eden Space","Par Survivor Space","PS Eden Space","PS Old Gen","PS Perm Gen","PS Survivor Space","CMS Old Gen","CMS Perm Gen","Perm Gen"]: 
            beanName = "java.lang:type={},name={}".format("MemoryPool", name)
            result = JmxUtils.queryBeanByNameAndAtrribute(beanName , "Usage")
            ins = {}
            if 'Usage' in result :
                attribute = 'Usage'
                data = result[attribute]
                max = memDivide(data['max'])
                used = memDivide(data['used'])
                init = memDivide(data['init'])
                committed = memDivide(data['committed'])
                ins['NAME'] = "{} {}".format(name , attribute)
                ins['MAX'] = max
                ins['USED'] = used
                ins['INIT'] = init
                ins['COMMITTED'] = committed
                ins['USAGE'] = usageDivide(used , max)
                memoryPool.append(ins)
        tomcat["MEMORYPOOL"] = memoryPool

        garbageCollector = []
        gcBeans = ["Copy","MarkSweepCompact","PS Scavenge","ConcurrentMarkSweep","ParNew","PS MarkSweep"]
        gcAttributes = ["CollectionTime","CollectionCount"]
        for beanName in gcBeans :
            ins = {}
            ins['NAME'] = beanName
            existAtrribute = 0 
            for atrributeName in gcAttributes :
                result = JmxUtils.queryBeanByTypeAndNameAtrribute("GarbageCollector" , beanName,  atrributeName )
                existAtrribute = 0 
                if atrributeName in result :
                    ins[atrributeName.upper()] = result[atrributeName][atrributeName]
                    if existAtrribute == 0  :
                        existAtrribute = 1
            if existAtrribute == 1 :
                garbageCollector.append(ins)
        tomcat["GARBAGECOLLECTOR"] = garbageCollector
        
        thread = {}
        thAttributes = ["ThreadCount" , "DaemonThreadCount" , "PeakThreadCount" , "TotalStartedThreadCount"]
        for atrributeName in thAttributes :
            result = JmxUtils.queryBeanByNameAndAtrribute("java.lang:type=Threading",  atrributeName )
            value = result[atrributeName][atrributeName]
            thread[atrributeName.upper()] = value
        tomcat["THREAD"] = thread

        threadPoolMap = {}
        threadPoolAttributes = ["connectionCount","currentThreadCount","currentThreadsBusy","maxThreads"]
        for atrributeName in threadPoolAttributes :
            result = JmxUtils.queryBeanByNameAndAtrribute("Catalina:name=*,type=ThreadPool",  atrributeName, "{name}")
            for key in result :
                data = result[key]
                ins = {} 
                if key in threadPoolMap :
                    ins = threadPoolMap[key]
                ins['NAME'] = key 
                if 'dict' in  str(type(data)) :
                    for dkey in data :
                        ins[dkey.upper()]= data[dkey] 
                threadPoolMap[key] = ins
        threadPool = []
        for key in threadPoolMap : 
            threadPool.append(threadPoolMap[key])
        tomcat["THREADPOOL"] = threadPool

        requestProcessorMap = {}
        requestProcessorAttributes = ["requestCount","errorCount","bytesReceived","bytesSent"]
        for atrributeName in requestProcessorAttributes :
            result = JmxUtils.queryBeanByNameAndAtrribute("Catalina:type=GlobalRequestProcessor,name=*",  atrributeName, "{name}")
            for key in result :
                data = result[key]
                ins = {} 
                if key in requestProcessorMap :
                    ins = requestProcessorMap[key]
                ins['NAME'] = key 
                if 'dict' in  str(type(data)) :
                    for dkey in data :
                        ins[dkey.upper()]= data[dkey] 
                requestProcessorMap[key] = ins
        requestProcessor = []
        for key in requestProcessorMap : 
            requestProcessor.append(requestProcessorMap[key])
        tomcat["REQUESTPROCESSOR"] = requestProcessor

        dataSource = {}
        dataSourceAttributes = ["maxTotal","numActive","initialSize","driverClassName"]
        for atrributeName in dataSourceAttributes :
            result = JmxUtils.queryBeanByNameAndAtrribute("Catalina:class=javax.sql.DataSource,context=*,host=*,name=*,type=DataSource",  atrributeName , '{name}')
            for key in result : 
                dataSource["NAME"] = key 
                data = result[key]
                for dkey in data :
                    dataSource[dkey.upper()] = data[dkey]
        tomcat["DATASOURCE"] = dataSource

        tomcat['AVAILABILITY'] = 1
        tomcat['ERROR_MESSAGE'] = ''
    else:
        tomcat['AVAILABILITY'] = 0
        tomcat['ERROR_MESSAGE'] = errMsg
    tomcat['RESPONSE_TIME'] = timeConsume
    
    out = {}
    out["DATA"] = [tomcat]
    AutoExecUtils.saveOutput(out)
        